<script>
import { deepClone, isFunction, isNull, isUndefined } from './util';

export default {
  name: 'vTableSelect',

  inject: {
    elForm: {
      default: '',
    },
    elFormItem: {
      default: '',
    },
  },

  props: {
    value: {
      type: [Object, Array, String, null, undefined],
      default: null,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: '请选择',
    },
    size: {
      type: String,
      default: 'small',
    },
    labelKey: {
      type: String,
      default: 'label',
    },
    valueKey: {
      type: String,
      default: 'value',
    },
    // 打开之前
    beforeOpen: {
      type: Function,
      default: null,
    },
    beforeClose: {
      type: Function,
      default: () => {
        return true;
      },
    },
    // 弹窗标题
    title: {
      type: String,
      default: '',
    },
    // 弹窗宽度
    width: {
      type: String,
      default: '50%',
    },
    // 默认选项数据
    defaultOptions: {
      type: Array,
      default: () => {
        return [];
      },
    },
    columns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    tableData: {
      type: Array,
      default: () => {
        return [];
      },
    },
    pagination: {
      type: Object,
      default: null,
    },
  },

  data() {
    return {
      search: '',
      visible: false,
      selected: [],
      popupSelected: [],
      cacheOptions: [],
      showSelectTable: false,
      animationStart: false,
      animationEnd: false,
    };
  },

  watch: {
    value: {
      immediate: true,
      handler() {
        this.setSelected();
      }
    },
    selected: {
      deep: true,
      handler() {
        this.setCacheOptions('selected');
      }
    },
    popupSelected: {
      deep: true,
      handler() {
        this.setCacheOptions('popupSelected');
      }
    },
    tableData: {
      deep: true,
      handler(val) {
        if(val.length) {
          this.setCacheOptions('tableData');
          this.selected.forEach((item, index) => {
            const data = this.tableData.find(e => e[this.valueKey] === item[this.valueKey]);
            if (data) {
              this.selected[index] = data;
            }
          })
        }
      }
    }
  },

  computed: {
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },
    inputSize() {
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
    },
    selectDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    },
    wrapperStyles() {
      return {
        transform: this.showSelectTable && this.animationStart ? 'translateX(0)' : undefined,
      };
    },
  },

  methods: {
    setSelected() {
      if (this.multiple) {
        this.selected = this.value?.map(value => this.getOption(value)) || [];
        return;
      }

      if (isNull(this.value) || isUndefined(this.value) || this.value === '') {
        this.selected = [];
        return;
      }

      let option = this.getOption(this.value);
      this.selected = [option];
    },

    getOption(value) {
      let option = this.tableData.find(e => e[this.valueKey] === value) 
        || this.cacheOptions.find(e => e[this.valueKey] === value)
        || this.defaultOptions.find(e => e[this.valueKey] === value);

      if (!option) {
        const label = isNull(value) || isUndefined(value) ? '' : value;
        option = {
          [this.labelKey]: value,
          [this.valueKey]: label,
        }
      }

      return option;
    },

    // 点击输入框
    async clickInputContent() {
      if (this.selectDisabled) {
        return;
      }

      if (this.beforeOpen && !await this.beforeOpen()) {
        return;
      }

      this.popupSelected = deepClone(this.selected) || [];
      this.visible = true;
    },

    deleteItem(event, item, index) {
      const selected = this.selected.filter((e, i) => i !== index);
      this.$emit('input', selected.map(e => e[this.valueKey]), selected);
      this.$emit('change', selected.map(e => e[this.valueKey]), selected);
      this.$emit('confirm', selected.map(e => e[this.valueKey]), selected);
      this.$emit('remove-tag', item);
    },

    async confirm() {
      if (this.beforeClose && isFunction(this.beforeClose)) {
        if (!await this.beforeClose()) {
          return;
        }
      }

      if (this.multiple) {
        this.$emit('input', this.popupSelected.map(e => e[this.valueKey]), this.popupSelected);
        this.$emit('change', this.popupSelected.map(e => e[this.valueKey]), this.popupSelected);
        this.$emit('confirm', this.popupSelected.map(e => e[this.valueKey]), this.popupSelected);
      } else {
        if (this.popupSelected?.[0]) {
          this.$emit('input', this.popupSelected[0][this.valueKey], this.popupSelected[0]);
          this.$emit('change', this.popupSelected[0][this.valueKey], this.popupSelected[0]);
          this.$emit('confirm', this.popupSelected[0][this.valueKey], this.popupSelected[0]);
        }
      }

      this.visible = false;
    },

    close() {
      this.$emit('close');
      this.visible = false;
    },

    handleSizeChange(val) {
      this.$emit('size-change', val);
    },

    handleCurrentChange(val) {
      this.$emit('current-change', val);
    },

    // 输入框
    createInput() {
      const { labelKey, multiple, size } = this;
      const className = {
        'v-table-select__input': true,
        'is-multiple': multiple,
      };

      let inputContent;

      if (multiple) {
        let multipleContent;

        if (!this.selected.length) {
          multipleContent = <span class="el-input__placeholder">{ this.placeholder }</span>;
        } else {
          multipleContent = this.selected?.map((item, index) => {
            const deleteItem = event => this.deleteItem(event, item, index);
            const content = item[labelKey];
            return (
              <el-tag
                hit
                type="info"
                closable={!this.selectDisabled}
                size={size}
                onClose={deleteItem}
              >
                <div class="el-select_tag_content">
                  <span class="el-select_tag_content-text">{content}</span>
                </div>
              </el-tag>
            )
          })
        }

        inputContent = (
          <div class={`el-input el-input--${size}`}>
            <div class="el-input__inner">
              { multipleContent }
            </div>
          </div>
        )
      } else {
        const label = this.selected?.[0]?.[this.labelKey] || '';
        inputContent = (<el-input value={label} placeholder={this.placeholder} size={size} readonly />)
      }

      return (
        <div ref="input" class={className} onClick={this.clickInputContent}>
          { inputContent }
        </div>
      )
    },

    clear() {
      this.$emit('input', '', '');
      this.$emit('clear', '', '');
    },

    // table点击行  并去设置选项
    onRowClick(row, column, cell, event) {
      this.selectItem(row);
      this.$emit('row-click', row, column, cell, event);
    },

    // 设置选项
    selectItem(row) {
      const index = this.popupSelected.findIndex(item => item[this.valueKey] === row[this.valueKey]);
      if (this.multiple) {
        if (index === -1) {
          this.popupSelected.push(row);
        } else {
          this.popupSelected.splice(index, 1);
        }
        return;
      }

      if (index === 0) {
        this.popupSelected.splice(0, 1);
      } else {
        this.popupSelected = [row];
      }
    },

    // 缓存选项 TODO: 暂时是全部缓存   后面可以筛选
    setCacheOptions(type) {
      let cacheIds = [...this.selected, ...this.popupSelected].map(e => e[this.valueKey]);
      cacheIds = Array.from(new Set(cacheIds));

      cacheIds.forEach(value => {
        const option = this.tableData.find(item => item[this.valueKey] === value);
        if (option) {
          const cacheIndex = this.cacheOptions.findIndex(item => item[this.valueKey] === value);
          if (cacheIndex === -1) {
            this.cacheOptions.push(option)
          } else {
            this.cacheOptions[cacheIndex] = option;
          }
        }
      })
    },

    // 当前列 是否选中
    getSelect(row) {
      return !!this.popupSelected.find(item => item[this.valueKey] === row[this.valueKey]);
    },

    // 创建选项table
    createTable(type) {
      if (type === 'content' && this.$slots.content) {
        return this.$slots.content;
      }

      let checkSlots;
      if (this.multiple) {
        checkSlots = {
          default: ({ row }) => {
            return (
              <div onClick={event => event.stopPropagation()}>
                <el-checkbox disabled={this.selectDisabled} value={this.getSelect(row)} onChange={() => this.selectItem(row)} />
              </div>
            )
          }
        }
      } else {
        checkSlots = {
          default: ({ row }) => {
            return (
              <div onClick={event => event.stopPropagation()}>
                <el-checkbox disabled={this.selectDisabled} value={this.getSelect(row)} onChange={() => this.selectItem(row)} />
              </div>
            )
          }
        }
      }

      const tableListener = {
        'row-click': this.onRowClick,
      };

      return (
        <div class="v-table-select__popup-table">
          <el-table
            ref="table"
            data={type === 'content' ? this.tableData : this.popupSelected}
            size="small"
            style="width: 100%"
            height="100%"
            max-height={type === 'content' ? '100%' : '400px'}
            hover
            border={false}
            row-key={this.valueKey}
            on={tableListener}
          >
            <el-table-column show-overflow-tooltip fixed="left" align="center" width="50" scopedSlots={checkSlots} />
            {
              this.columns.map(column => {
                return <el-table-column show-overflow-tooltip label={column.label} prop={column.prop} { ...{ props: column?.props || {} } } />
              })
            }
          </el-table>
        </div>
      )
    },

    afterEnter() {
      this.animationStart = true;
      this.animationEnd = false;
    },
  
    afterLeave() {
      this.animationStart = false;
      this.animationEnd = true;
    },

    // 创建已选table
    createSelectedTable() {
      if (this.multiple) {
        const duration = { enter: 100, leave: 300 };
        const close = () => this.showSelectTable = false;
        return (
          <transition
            duration={duration}
            onAfterEnter={this.afterEnter}
            onAfterLeave={this.afterLeave}
          >
            <div
              v-show={this.showSelectTable}
              class="v-table-select__selected-popup"
              tabindex={0}
              ref="drawerContainer"
              onClick={close}
            >
              <div class="v-table-select__selected-popup-content" style={this.wrapperStyles} onClick={event => event.stopPropagation()}>
                { this.createTable('selected') }
              </div>
            </div>
          </transition>
        );
      }
    },

    // 创建已选标记
    createSelectedTag() {
      if (this.multiple) {
        const changeShowSelectTable = () => {
          this.showSelectTable = !this.showSelectTable;
        }
        return (
          <div class="v-table-select__footer-popupSelected" onClick={changeShowSelectTable}>
            <el-tooltip effect="dark" content={`已选择${this.popupSelected.length || 0}条数据`}>
              <el-button size="small" type="text" theme={this.popupSelected.length > 0 ? 'primary' : 'default'}>
                <el-icon svg name="view-list"></el-icon>已选择&nbsp;&nbsp;{ this.popupSelected.length ||  0 }
              </el-button>
            </el-tooltip>
          </div>
        )
      }
    },

    // 弹窗
    createPopup() {
      let searchContent = '';
      if (this.$slots.search) {
        searchContent = (
          <div class="v-table-select__search">
            { this.$slots.search }
          </div>
        )
      }

      let paginationContent = '';
      if (this.pagination) {
        const paginationListener = {
          'size-change': this.handleSizeChange,
          'current-change': this.handleCurrentChange,
        }
        paginationContent = (
          <div class="v-table-select__pagination">
            <el-pagination
              small
              layout="total, ->,  prev, pager, next"
              total={this.pagination.total}
              pageSize={this.pagination.pageSize}
              currentPage={this.pagination.currentPage}
              on={paginationListener}
            />
          </div>
        )
      }

      return (
        <el-drawer
          visible={this.visible}
          title={this.title}
          size={this.width}
          destroy-on-close={true}
          close-on-press-escape={false}
          wrapperClosable={false}
          custom-class="v-table-select__popup-wrapper"
          onClose={this.close}
          onConfirm={this.confirm}
        >
          <div class="v-table-select__popup-content">
            { searchContent }
            { this.createTable('content') }
            { paginationContent }
            { this.createSelectedTable() }
          </div>
          <div class="v-table-select__popup-footer">
            { this.createSelectedTag() }
            <div class="v-table-select__popup-footer-btns">
              <el-button size="small" onClick={this.close}>
                取消
              </el-button>
              <el-button size="small" type="primary" theme="primary" onClick={this.confirm}>
                确认
              </el-button>
            </div>
          </div>
        </el-drawer>
      )
    }
  },

  render() {
    return (
      <div class="v-table-select">
        { this.createInput() }
        { this.createPopup() }
      </div>
    )
  }
};
</script>


<style lang="scss">
@import "../style/index.scss";
</style>